﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using log4net;
using System.Web.Security;
using System.Configuration;
using System.Net.Mail;
using System.Data.SqlClient;
using BoardPACDSWeb.Lang;
using BoardPACDSBO.General;
using BoardPACDSWeb.Models.General;
using BoardPACDSWeb.Models.Auth;
using BoardPACDSWeb.AuthorizeServiceReference;
using System.ServiceModel;
using BoardPACDSBO.Auth;
using BoardPACDSWeb.AnonymousUserServiceReference;
using BoardPACDSBO.UserMgt;
using System.ServiceModel.Security;


namespace BoardPACDSWeb.Controllers
{
    /// <summary>
    /// 
    ///  <title>BoardPAC AdminController</title>
    ///  <description>LogOnController for LogOn LogOff actions</description>
    ///  <copyRight>Copyright (c) 2011</copyRight>
    ///  <company>IronOne Technologies (Pvt)Ltd</company>
    ///  <createdOn>2011-10-18</createdOn>
    ///  <author></author>
    ///  <modification>
    ///     <modifiedBy></modifiedBy>
    ///      <modifiedDate></modifiedDate>
    ///     <description></description>
    ///  </modification>
    ///
    /// </summary>
    public class LogOnController : BaseController
    {
        protected static ILog EventLog = LogManager.GetLogger("EventLog");
        protected static ILog ErrorLog = LogManager.GetLogger("ErrorLog");

        FormsAuthenticationService FormsService = new FormsAuthenticationService();

        ///GetUserGuid return method
        ///<returns>
        ///Returns the GUID of the current user
        ///</returns>
        ///<exception cref="">
        ///
        /// </exception>
        /// <remarks></remarks>
        public Guid GetUserGuid()
        {
            EventLog.Info(String.Format(Resources.log_evt_entry_GetUserGuid, EventStatus.Debug.ToString()));

            Guid a = new Guid();
            try
            {
                using (AuthorizeClient client = new AuthorizeClient())
                {
                    SetCredentials(client);
                    a = client.GetUserGuid(User.Identity.Name);
                }
            }
            catch (FaultException<BoardPACDSWeb.AuthorizeServiceReference.GenFault> e)
            {
                //TODO: log on Exception
                throw new GenException(e.Detail.Code);
            }
            catch (FaultException)
            {
                //TODO: log on Exception
                throw new GenException("err_111_sys");
            }
            catch (Exception e)
            {
                ErrorLog.Error("0, ERR, " + EventStatus.Failure.ToString() + ", LogOn, GetUserGuid, " + e.Message + " ," + e.InnerException + ", Stack Trace: " + e.StackTrace);
                throw new GenException("err_111_sys");
            }
            return a;
        }

        /// <summary>
        /// Call at the first load of login page
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ActionResult LogOn(LogOnModel model)
        {
            EventLog.Info(String.Format(Resources.log_evt_entry_LogOn, EventStatus.Entry.ToString(), Request.ServerVariables["REMOTE_ADDR"]));
            Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_LogOn, EventStatus.Entry.ToString(), Request.ServerVariables["REMOTE_ADDR"]));

            // Check user is Authenticated
            if (User.Identity.IsAuthenticated)
            {
                //For Authenticated User
                EventLog.Info(String.Format(Resources.log_evt_success_LogOn, EventStatus.Success.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, model.RememberMe));
                Logs.WriteLogToDb(String.Format(Resources.log_evt_success_LogOn, EventStatus.Success.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, model.RememberMe));
                return GetFormatView("Home/Home.aspx");
            }
            else
            {
                try
                {
                    if (GetFormat().ToUpper().Equals("XML"))
                        throw new GenException("err_110");
                }

                catch (Exception e)
                {
                    ModelState.AddModelError("err", e);
                    ErrorLog.Error("0, " + "ERR, " + EventStatus.Failure.ToString() + ", LogOn" + ",LogOn, Client IP Address: " + Request.ServerVariables["REMOTE_ADDR"] + "," + e.Message);
                    EventLog.Info(String.Format(Resources.log_err_0_LogOn, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], e.Message));
                    Logs.WriteLogToDb(String.Format(Resources.log_err_0_LogOn, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], e.Message));
                }

                // Check the session and if it's not a new one and IsAuthenticated == false
                // definitely it's cause of a session expiration
                if (!Session.IsNewSession)  //if not a new session
                {
                    TempData["errMsg"] = "Your session has been expired!";
                }

                return GetFormatView("Auth/LogOn.aspx");
            }
        }

        ///LogOn Action Method
        ///<param name="model">LogOnModel</param>
        ///<param name="returnUrl">return URL</param>
        ///<returns>
        ///If successfully logged on goes to Default/Index or the return url
        ///</returns>       
        ///<exception cref="">
        ///Same view with the error
        /// </exception>
        /// <remarks></remarks>
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl = "")
        {
            String IsiPadRequest = "";
            try
            {
                EventLog.Info(String.Format(Resources.log_evt_entry_LogOnPOST, EventStatus.Entry.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, model.RememberMe, returnUrl));
                Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_LogOnPOST, EventStatus.Entry.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, model.RememberMe, returnUrl));

                //getting the deviceId
                RequestHeader req = GetHeaderLogDetails();
                String device = (req == null) ? device = null : device = req.deviceId;
                String mac = (req == null) ? mac = null : mac = req.macAddress;
                IsiPadRequest = GetFormat() == "XML" ? "IPAD" : String.Empty;

                if (User.Identity.IsAuthenticated)
                {
                    return GetFormatView("Home/Home.aspx");
                }

                if (model.UserName == null && model.Password == null) throw new GenException("err_100");
                else if (model.UserName == null) throw new GenException("err_101");
                else if (model.Password == null) throw new GenException("err_102");

                if (ModelState.IsValid)
                {
                    SetCredentials(model.UserName, model.Password);
                    using (AuthorizeClient client = new AuthorizeClient())
                    {
                        client.ClientCredentials.UserName.UserName = model.UserName;
                        client.ClientCredentials.UserName.Password = model.Password;

                        try
                        {
                            client.UnlockUser(model.UserName);
                        }
                        catch (MessageSecurityException e)
                        {
                            ModelState.AddModelError("err", new GenException("err_104"));
                            return GetFormatView("Auth/LogOn.aspx");
                        }

                        if (client.ValidateUser(model.UserName, model.Password))
                        {
                            EventLog.Info(String.Format(Resources.log_evt_success_LogOnPOST, EventStatus.Success.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, IsiPadRequest));
                            Logs.WriteLogToDb(String.Format(Resources.log_evt_success_LogOnPOST, EventStatus.Success.ToString(), Request.ServerVariables["REMOTE_ADDR"], model.UserName, IsiPadRequest));
                            FormsService.SignIn(model.UserName, model.RememberMe);
                            Session.Add("fmt", Request.Params.Get("fmt"));

                            if (!String.IsNullOrEmpty(returnUrl))
                            {
                                return Redirect(returnUrl);
                            }
                            else
                            {
                                if (Session["fmt"] != null)
                                {
                                    if (Request.Params.Get("fmt").ToUpper().Equals("XML"))
                                    {
                                        bool iPadAllowed = client.IsIPadAllowed(model, req, Session["fmt"].ToString());

                                        if (iPadAllowed)
                                        {
                                            ViewData["iPadLogOnResponse"] = RespondIpadonLogOn(model, req);
                                        }
                                        else
                                        {
                                            ModelState.AddModelError("err", new GenException("err_112"));
                                        }
                                        return GetFormatView("Home/Home.aspx");
                                    }
                                }
                                else
                                {
                                    return RedirectToAction("Index", "Default");
                                }
                            }
                        }
                        else
                        {
                            EventLog.Info(String.Format(Resources.log_err_104_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], IsiPadRequest));
                            Logs.WriteLogToDb(String.Format(Resources.log_err_104_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], IsiPadRequest));
                            throw new GenException("err_104");
                        }
                    }
                }
            }
            catch (GenException e)
            {
                EventLog.Info(String.Format(Resources.log_err_0_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], e.Message) + " " + IsiPadRequest);
                Logs.WriteLogToDb(String.Format(Resources.log_err_0_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], e.Message) + " " + IsiPadRequest);
                ErrorLog.Error(String.Format("0, " + "ERR, " + "{0}" + ", LogOn" + ",LogOn, Client IP Address: " + "{1}" + ", {2}", EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"], e.Message));
                ModelState.AddModelError("err", e);

            }
            catch (SqlException e)
            {
                EventLog.Info(String.Format(Resources.log_err_105_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"]) + IsiPadRequest + " " + Resources.err_105);
                Logs.WriteLogToDb(String.Format(Resources.log_err_105_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"]) + IsiPadRequest + " " + Resources.err_105);
                ErrorLog.Error("105, " + "ERR, " + EventStatus.Failure.ToString() + ", LogOn" + ", LogOn, Client IP Address: " + Request.ServerVariables["REMOTE_ADDR"] + "," + Resources.err_105 + ", " + e);
                ModelState.AddModelError("err", new GenException("err_105"));
            }
            catch (Exception e)
            {
                EventLog.Info(String.Format(Resources.log_err_109_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"]) + IsiPadRequest + " " + Resources.err_109);
                Logs.WriteLogToDb(String.Format(Resources.log_err_109_LogOnPOST, EventStatus.Failure.ToString(), Request.ServerVariables["REMOTE_ADDR"]) + IsiPadRequest + " " + Resources.err_109);
                ErrorLog.Error("109, " + "ERR, " + EventStatus.Failure.ToString() + ", LogOn" + ", LogOn, Client IP Address: " + Request.ServerVariables["REMOTE_ADDR"] + ", " + Resources.err_109 + ", " + e);
                ModelState.AddModelError("err", new GenException("err_109"));
            }
            return GetFormatView("Auth/LogOn.aspx");
        }

        [Authorize]
        public ActionResult LogOff()
        {
            EventLog.Info(String.Format(Resources.log_evt_entry_LogOff, EventStatus.Entry.ToString(), User.Identity.Name));
            Logs.WriteLogToDb(String.Format(Resources.log_evt_entry_LogOff, EventStatus.Entry.ToString(), User.Identity.Name));
            //string a = Request.ServerVariables["REMOTE_ADDR"]; 

            try
            {
                if (GetFormat() == "XML")
                {
                    FormsService.SignOut();
                    Session.Abandon();
                    EventLog.Info(String.Format(Resources.log_evt_success_LogOff, EventStatus.Success.ToString(), User.Identity.Name) + " iPad");
                    Logs.WriteLogToDb(String.Format(Resources.log_evt_success_LogOff, EventStatus.Success.ToString(), User.Identity.Name) + " iPad");
                    return GetFormatView("Home/LogOff.aspx");
                }
                else
                {
                    FormsService.SignOut();
                    Session.Abandon();
                    EventLog.Info(String.Format(Resources.log_evt_success_LogOff, EventStatus.Success.ToString(), User.Identity.Name));
                    Logs.WriteLogToDb(String.Format(Resources.log_evt_success_LogOff, EventStatus.Success.ToString(), User.Identity.Name));
                }
            }
            catch (Exception e)
            {
                // User cannot logout at this moment.
                EventLog.Info(String.Format(Resources.log_err_117_LogOff, EventStatus.Failure.ToString(), User.Identity.Name) + Resources.err_117);
                Logs.WriteLogToDb(String.Format(Resources.log_err_117_LogOff, EventStatus.Failure.ToString(), User.Identity.Name) + Resources.err_117);
            }
            return RedirectToAction("LogOn", "LogOn");
        }

        [Authorize]
        public ActionResult NotAuthorized()
        {
            EventLog.Info(String.Format(Resources.log_evt_entry_NotAuthorized, EventStatus.Entry.ToString(), User.Identity.Name));
            return GetFormatView("Auth/NotAuthorized.aspx");
        }

        #region XmlActions

        public IPADLogOnModel RespondIpadonLogOn(LogOnModel model, RequestHeader request)
        {
            //EventLog.Info(String.Format(Resources.log_evt_entry_RespondIpadonLogOn, EventStatus.Entry.ToString(), User.Identity.Name, model.UserName, model.ReturnURL, request.deviceId, request.macAddress));

            if (GetFormat().Equals("XML"))
            {
                IPADLogOnModel iPadLM = new IPADLogOnModel();
                try
                {
                    using (AnonymousUserServiceClient anoClient = new AnonymousUserServiceClient())
                    {
                        using (AuthorizeClient client = new AuthorizeClient())
                        {
                            client.ClientCredentials.UserName.UserName = model.UserName;
                            client.ClientCredentials.UserName.Password = model.Password;

                            UserMgtModelsMetadata user = client.GetUser(model.UserName);

                            iPadLM.UserName = model.UserName;
                            iPadLM.Password = model.Password;
                            iPadLM.UserID = user.customUserId;
                            iPadLM.UserFullName = user.firstName + " " + user.lastname;
                            iPadLM.UserRoles1 = new List<UserRole>();
                            iPadLM.roleOfuser = new List<RoleOfUser>();
                            iPadLM.PasswordReseted = user.passwordReseted;

                            string[] userRoles = new string[] { user.roleName };
                            iPadLM.UserRoles1 = client.GetUserRoles(userRoles.ToList());

                            iPadLM.roleOfuser = client.GetRoleOfUser(user.customUserId);

                            //checking for the device already registered
                            anoClient.IsDeviceAllowed(request);

                            int RegistreredDeviceCount = client.GetRegisteredDiviceCount(request);

                            if (RegistreredDeviceCount > 0)
                            {
                                iPadLM.DeviceRegStatus = "Device registered for the user";
                            }
                            else
                            {
                                iPadLM.DeviceRegStatus = "Device not registered for the user";
                                ModelState.AddModelError("err", new GenException("err_153"));
                                FormsService.SignOut();
                                Session.Abandon();
                            }
                        }
                    }
                }
                catch (FaultException<BoardPACDSWeb.AuthorizeServiceReference.GenFault> e)
                {
                    //TODO: log on Exception
                    ModelState.AddModelError("err", new GenException(e.Detail.Code));
                }
                catch (FaultException<BoardPACDSWeb.AnonymousUserServiceReference.GenFault> e)
                {
                    //TODO: log on Exception
                    ModelState.AddModelError("err", new GenException(e.Detail.Code));
                }
                catch (FaultException)
                {
                    //TODO: log on Exception
                    ModelState.AddModelError("err", new GenException("err_1001"));
                }
                catch (Exception e)
                {
                    ModelState.AddModelError("err", e);
                }
                return iPadLM;
            }
            return null;
        }

        /*
        public IPADLogOnModel RespondIpadonLogOn(LogOnModel model, string deviceId, string macAddress, RequestHeader request)
        {
            EventLog.Info(String.Format(Resources.log_evt_entry_RespondIpadonLogOn, EventStatus.Entry.ToString(), User.Identity.Name, model.UserName, model.ReturnURL, deviceId));
            try
            {
                if (GetFormat().Equals("XML"))
                {
                    IPADLogOnModel iPadLM = new IPADLogOnModel();

                    using (AnonymousUserServiceClient anoClient = new AnonymousUserServiceClient())
                    {
                        using (AuthorizeClient client = new AuthorizeClient())
                        {
                            client.ClientCredentials.UserName.UserName = model.UserName;
                            client.ClientCredentials.UserName.Password = model.Password;

                            UserMgtModelsMetadata user = client.GetUser(model.UserName);

                            iPadLM.UserName = model.UserName;
                            iPadLM.Password = model.Password;
                            iPadLM.UserID = user.customUserId;
                            iPadLM.UserFullName = user.firstName + " " + user.lastname;
                            iPadLM.UserRoles1 = new List<UserRole>();
                            iPadLM.roleOfuser = new List<RoleOfUser>();
                            iPadLM.PasswordReseted = user.passwordReseted;

                            string[] userRoles = new string[] { user.roleName };
                            iPadLM.UserRoles1 = client.GetUserRoles(userRoles.ToList());

                            iPadLM.roleOfuser = client.GetRoleOfUser(user.customUserId);


                            //checking for the device already registered
                            anoClient.IsDeviceAllowed(request);

                            int RegistreredDeviceCount = client.GetRegisteredDiviceCount(request);

                            if (RegistreredDeviceCount > 0)
                            {
                                iPadLM.DeviceRegStatus = "Device registered for the user";
                                EventLog.Info(String.Format(Resources.log_evt_success_RespondIpadonLogOn, EventStatus.Success.ToString(), User.Identity.Name, model.UserName, model.ReturnURL, deviceId, macAddress));
                            }
                            else
                            {
                                iPadLM.DeviceRegStatus = "Device not registered for the user";
                                ModelState.AddModelError("err", new GenException("err_153"));
                                FormsService.SignOut();
                                Session.Abandon();
                            }
                        }
                    }
                    return iPadLM;
                }
            }
            catch (FaultException<BoardPACDSWeb.AuthorizeServiceReference.GenFault> e)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException(e.Detail.Code));
            }
            catch (FaultException<BoardPACDSWeb.AnonymousUserServiceReference.GenFault> e)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException(e.Detail.Code));
            }
            catch (FaultException)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException("err_1001"));
            }
            catch (Exception e)
            {
                ModelState.AddModelError("err", e);
            }
            return null;
        }
        */

        #endregion XmlActions

        #region PasswordManagement

        public string AlertLoginExpiry()
        {
            string alert = string.Empty;
            try
            {
                if (User != null)
                {
                    using (AuthorizeClient client = new AuthorizeClient())
                    {
                        SetCredentials(client);
                        MemberModel mUser = client.GetMembershipUser(User.Identity.Name);

                        int expPeriod = int.Parse(ConfigurationManager.AppSettings["PasswordExpiryPeriod"]);
                        int expAlertPeriod = int.Parse(ConfigurationManager.AppSettings["PasswordExpiryAlertPeriod"]);
                        if (mUser.LastPasswordChangedDate.AddDays(expPeriod - expAlertPeriod) <= DateTime.Now)
                        {
                            int expiryAlertdays = (mUser.LastPasswordChangedDate.AddDays(expPeriod) - DateTime.Now).Days;
                            if (expiryAlertdays > 0)
                            {
                                alert = String.Format(Resources.info_PasswordExpirywarning, expiryAlertdays.ToString());
                            }
                            else
                            {
                                alert = Resources.info_PasswordExpiredMsg;
                                MembershipServiceModel membership = client.GetMembershipService();
                                ViewData["PasswordLength"] = membership.MinPasswordLength;
                                ViewData["NonAlphaNumericInPassword"] = membership.MinNonAlphanumericCharacters;
                                View("~/Views/HTML/Auth/ChangePassword.aspx", null);
                            }
                            EventLog.Info(String.Format(Resources.log_evt_success_AlertLoginExpiry, EventStatus.Success.ToString(), mUser.UserName));
                        }
                    }
                }
            }
            catch (FaultException<BoardPACDSWeb.AnonymousUserServiceReference.GenFault> e)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException(e.Detail.Code));
            }
            catch (FaultException<BoardPACDSWeb.AuthorizeServiceReference.GenFault> e)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException(e.Detail.Code));
            }
            catch (FaultException)
            {
                //TODO: log on Exception
                ModelState.AddModelError("err", new GenException("err_109"));
            }
            catch (Exception e)
            {
                // Login expires is not working at this moment.
                EventLog.Info(String.Format(Resources.log_err_380_AlertLoginExpiry, EventStatus.Failure.ToString(), User.Identity.Name) + Resources.err_109);
                ModelState.AddModelError("err", e);
            }
            return alert;
        }

        #endregion PasswordManagement
    }
}
